<script>
  import $ from '../dfish.js'
  import {
    h,
    mergeProps
  } from 'vue'
  import WidgetBase from './WidgetBase.vue'
  import SrcParent from './SrcParent.vue'
  import TripleBox from './TripleBox.vue'
  import Img from './Img.vue'

  export default {
    name: 'w-leaf',
    pubParentName: 'w-tree',
    mixins: [WidgetBase, SrcParent],
    props: ['text', 'expandedIcon', 'collapsedIcon', 'expanded', 'boxSync', 'br', 'format', 'folder', 'src', 'success',
      'filter', 'error', 'complete'
    ],
    inject: ['providePubParent', 'provideLeafLevel', 'provideParentLeaf'],
    provide() {
      return {
        provideParentLeaf: this,
        provideLeafLevel: this.provideLeafLevel + (this.isEntity ? 1 : 0),
        provideBoxParent: this,
      }
    },
    data() {
      return {
        hover: false,
        loading: false,
        loaded: this.inTree() ? this.getInitLoaded() : this.provideParentLeaf.getInitLoaded(),
      }
    },
    methods: {
      hasChild() {
        return this.inTree() ? $.hasChild(this.$slots) : this.provideParentLeaf.hasChild()
      },
      children() {
        return $.lodash.map(this.$refs.cont.querySelectorAll(':scope > .w-leaf'), v => $(v))
      },
      getInitLoaded() {
        return this.hasChild() || ((this.x || this.$props).folder === false) || !this.getSrc() ? true : false
      },
      inTree() {
        return !this.provideParentLeaf || this.provideParentLeaf.$options.name === 'w-leaf'
      },
      isExpanded() {
        return this.inTree() ? this.x.expanded : this.provideParentLeaf.isExpanded()
      },
      isFolder() {
        return this.inTree() ? (this.hasChild() ? true : this.x.folder != null ? this.x.folder : !!(this.getSrc() && !
          this.loaded)) : this.provideParentLeaf.isFolder()
      },
      toggle(exp, fn) {
        if (this.inTree()) {
          this.x.expanded = exp != null ? exp : !this.x.expanded
          if (this.isExpanded() && !this.loaded) {
            this.request(() => {
              fn && fn(this.isExpanded())
            })
          } else {
            fn && this.$nextTick(() => {
              fn(this.isExpanded())
            })
          }
        } else {
          this.provideParentLeaf.toggle(exp, fn)
        }
      },
      clickBoxProxy(e) {
        this._triple()
      },
      clickText(e) {
        if (this.boxProxy && this.x.boxSync) {
          this.boxProxy.check(!this.boxProxy.isChecked)
          this._triple()
        }
      },
      // triplebox 级联勾选
      _triple() {
        let p = this
        while ((p = p.provideParentLeaf) && p.$options.name === 'w-leaf') {
          if (p.boxProxy) {
            let c = p.children()
            let m = [0, 0, 0]
            let l = c.length
            c.forEach(v => {
              let b = v.boxProxy
              if (b) m[b.checkstate()]++
            })
            p.boxProxy.check(m[0] === l ? 0 : m[1] === l ? 1 : 2)
          }
        }
        let c = this.boxProxy.checkstate()
        c != 2 && this._tripleAll(c)
      },
      _tripleAll(a) {
        this.children().forEach(v => {
          if (v.boxProxy) {
            v.boxProxy.check(a)
            v._tripleAll(a)
          }
        })
      },
      onmouseenter(e) {
        this.el().classList.add('z-hv')
      },
      onmouseleave(e) {
        this.el().classList.remove('z-hv')
      },
      onbeforescrollintoview() {
        let p = this
        while ((p = p.provideParentLeaf) && (p.$options.name === this.$options.name)) {
          p.toggle(true)
        }
      },
      html_self() {
        let exp = this.isExpanded()
        let ico = exp ? this.x.expandedIcon : this.x.collapsedIcon
        return h('div', mergeProps(this.html_attrs, this.$attrs, this.html_props), [
          this.loading ?
          h(Img, {
            src: '#f-svg-loading',
            class: 'w-leaf-loading'
          }) :
          h('div', {
            class: ['w-leaf-toggle f-i', exp ? 'f-i-caret-down' : 'f-i-caret-right'],
            onclick: (e) => {
              e.stopPropagation(), this.toggle()
            }
          }),
          this.$slots.box && this.$slots.box(),
          ico && h(Img, {
            src: ico,
            class: ['w-leaf-icon', {
              'z-expanded': exp,
              'z-collapse': !exp
            }],
          }),
          h('div', {
            class: 'w-leaf-text' + ($.isNumber(this.x.br) ? ' f-line-' + this.x.br : this.x.br ? '' :
              ' f-line-1'),
            title: this.x.text,
            onclick: this.clickText,
          }, this.$slots.text ? this.$slots.text() : this.x.text)

        ])

      },
      html_cont() {
        return h('div', {
          id: this.uid + 'cont',
          ref: 'cont',
          class: 'w-leaf-cont',
          style: {
            display: this.x.expanded ? '' : 'none'
          },
        }, this.$slots)
      },
      html() {
        return [this.html_self(), this.html_cont()]
      }
    },
    computed: {
      tree() {
        return this.pubParent
      },
      isCurrent() {
        return this.pubParent && this.pubParent.inCurrent(this)
      },
      html_props() {
        let prop = {
          class: {
            'z-folder': this.isFolder(),
              'z-on': this.isCurrent,
          },
          style: 'padding-left:' + $.unitSize((this.provideLeafLevel + 1) * 16),
        }
        if (this.inTree()) {
          prop.onmouseenter = this.onmouseenter
          prop.onmouseleave = this.onmouseleave
        }
        return prop
      }
    },
    mounted() {
      if (this.x.expanded) this.toggle(true)
      if (this.isCurrent) this.onbeforescrollintoview()
      if (this.boxProxy) {
        this.$nextTick(() => {
          if (!this.isFolder() && !this.$refs.cont.nextElementSibling) {
            this._triple()
          }
        })
      }
    }

  }
</script>

<style>
  .w-leaf {
    display: flex;
    align-items: center;
    box-sizing: border-box;
    min-height: 30px;
  }

  .w-leaf-text {
    flex: 1;
  }

  .w-leaf-toggle {
    visibility: hidden;
    padding: 0 1px;
    margin-left: 1px;
    color: #777;
  }

  .w-leaf-loading {
    width: 20px;
    margin-left: 1px;
  }

  .w-leaf-icon {
    margin-right: 6px;
  }

  .w-leaf.z-folder .w-leaf-toggle {
    visibility: visible;
  }

  .w-leaf .w-triplebox {
    margin-right: 6px;
  }
</style>
